package org.akomantoso.core.data;

import java.io.IOException;

import org.akomantoso.core.io.Externalizable;
import org.akomantoso.core.io.Input;
import org.akomantoso.core.io.Output;
import org.akomantoso.core.visitor.AKVisitor;


/**
 * The complex type basehierarchy is not used by any element, but is derived by other types to contain the basic
 * structure of hierarchical elements.
 * 
 * <pre>
 * 	<xsd:complexType name="basehierarchy">
 * 		<xsd:sequence>
 * 			<xsd:element ref="num" minOccurs="0" maxOccurs="1"/>
 * 			<xsd:element ref="heading" minOccurs="0" maxOccurs="1"/>
 * 			<xsd:element ref="subheading" minOccurs="0" maxOccurs="1"/>
 * 		</xsd:sequence>
 * 	</xsd:complexType>
 * </pre>
 * 
 * <p>
 * The element num is a heading element in a hierarchy that contains a number or any other ordered mechanism to identify
 * the structure.
 * </p>
 * 
 * <p>
 * the element heading is a heading element in a hierarchy that contains a title or any other textual content to
 * describe the structure.
 * </p>
 * 
 * <p>
 * the element subheading is a heading element in a hierarchy that contains a subtitle or any other textual content to
 * further describe the structure.
 * </p>
 * 
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 * 
 * @since http://www.akomantoso.org/1.0
 */
public abstract class BaseHierarchy implements Externalizable {

	private Num _num;
	private Heading _heading;
	private SubHeading _subheading;

	public Num getNum() {
		return _num;
	}

	public void setNum(Num num) {
		_num = num;
	}

	public Heading getHeading() {
		return _heading;
	}

	public void setHeading(Heading heading) {
		_heading = heading;
	}

	public SubHeading getSubheading() {
		return _subheading;
	}

	public void setSubheading(SubHeading subheading) {
		_subheading = subheading;
	}

	/**
	 * @see org.akomantoso.core.io.Externalizable#writeExternal(org.akomantoso.core.io.Output)
	 */
	public <T extends Output> void writeExternal(T out) throws IOException {
		if (_num != null) {
			_num.writeExternal(out);
		}
		if (_heading != null) {
			_heading.writeExternal(out);
		}
		if (_subheading != null) {
			_subheading.writeExternal(out);
		}
	}

	/**
	 * @see org.akomantoso.core.io.Externalizable#readExternal(org.akomantoso.core.io.Input)
	 */
	public <T extends Input> void readExternal(T in) throws IOException {
		final String localName = in.getLocalName();
		in.readNextStartElement();
		
		if (Num.ELEMENT.equals(in.getLocalName())) {
			_num = new Num();
			_num.readExternal(in);
			in.readNextStartOrEndElement();
			if (localName.equals(in.getLocalName())) {
				return;
			} 
		}
		
		if (Heading.ELEMENT.equals(in.getLocalName())) {
			_heading = new Heading();
			_heading.readExternal(in);
			
			in.readNextStartOrEndElement();
			if (localName.equals(in.getLocalName())) {
				return;
			} 
		}
		
		if (SubHeading.ELEMENT.equals(in.getLocalName())) {
			_subheading = new SubHeading();
			_subheading.readExternal(in);
			in.readNextStartOrEndElement();
		}
		
	}
	
	protected void internalAccept(AKVisitor visitor) {
		if (_num != null) {
			_num.accept(visitor);
		}
		if (_heading != null) {
			_heading.accept(visitor);
		}
		if (_subheading != null) {
			_subheading.accept(visitor);
		}
	}
	
}